package com.snail.common.sequence.utils;

import com.alibaba.fastjson2.JSON;
import com.snail.common.core.constant.SecurityConstants;
import com.snail.common.core.exception.ServiceException;
import com.snail.common.core.text.Convert;
import com.snail.common.core.utils.StringUtils;
import com.snail.common.lock.Lock;
import com.snail.common.redis.service.RedisService;
import com.snail.common.sequence.config.SequenceConfig;
import com.snail.common.sequence.config.SequenceProperties;
import com.snail.common.sequence.constants.SequenceConstants;
import com.snail.common.sequence.feign.RemoteSequenceService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Description: 序列号生成工具
 * @Author: Snail
 * @CreateDate: 2023/8/18 16:55
 * @Version: V1.0
 */
@Component
public class SequenceUtils {

    @Autowired
    private RedisService redisService;
    @Autowired
    private SequenceProperties sequenceProperties;
    @Autowired
    private RemoteSequenceService remoteSequenceService;
    @Autowired
    private Lock lock;

    /**
     * 生成序列号
     *
     * @param sequenceCode 序列号规则编码
     * @return 序列号
     */
    @SneakyThrows
    public String getSequence(String sequenceCode) {
        if (StringUtils.isEmpty(sequenceCode)) {
            throw new ServiceException("序号号规则编码不能为空!");
        }
        String sequenceKey = StringUtils.format(SequenceConstants.SEQUENCE_CODE_KEY, sequenceCode);
        String sequenceRule = StringUtils.format(SequenceConstants.SEQUENCE_CONFIG_KEY, sequenceCode);
        String sequenceLock = StringUtils.format(SequenceConstants.LOCK_KEY, sequenceCode);
        String sequence = "";
        //获取分布式锁
        if (!this.lock.getLock(sequenceLock)) {
            return sequence;
        }
        try {
            SequenceConfig config = SequenceConfig.builder().sequenceCode(sequenceCode).build();
            //从redis中获取序列
            sequence = Convert.toStr(redisService.getCacheLeftPop(sequenceKey));
            //如果没有获取就生成
            if (StringUtils.isEmpty(sequence)) {
                sequence = remoteSequenceService.generateSequence(sequenceCode, SecurityConstants.INNER);
            } else {
                //获取redis的序列号配置
                String configJson = redisService.getCacheObject(sequenceRule);
                if (StringUtils.isNotEmpty(configJson)) {
                    config = JSON.parseObject(configJson, SequenceConfig.class);
                }
                //补充redis序列号数据
                Long count = redisService.getCacheListCount(sequenceKey);
                Long threshold = config.getThreshold() == null ? 0L : config.getThreshold();
                if (count <= threshold) {
                    //预生成数量 - 剩余数量
                    Long generateNum = config.getGenerateNum() - count;
                    remoteSequenceService.generateBatchSequence(sequenceCode, generateNum, SecurityConstants.INNER);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放锁
            this.lock.unLock(sequenceLock);
        }
        return sequence;
    }

}
